#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <map>
#include <set>
#include<ostream>
#include<algorithm>
using std::ostream;
using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::ifstream;
using std::ofstream;
using std::istringstream;
using std::map;
using std::set;
using std::vector;
using std::cout;
using std::endl;

class QueryResult;
class TextQuery
{
public:
    void readFile(const string filename);
    QueryResult query(const string & word);
    vector<string>& getVector(){
        return _lines;
    }
private:
    vector<string> _lines;
    map<string, set<int> > _wordNumbers;
    map<string, int> _dict;
};

class QueryResult{
public:
    QueryResult () = default;
    QueryResult(string world,set<int>&idx,vector<string>&lines)
    :_world(world)
    ,_idx_line(idx)
    ,_lines(lines){}

    //为了后续使用集合
    //获取开始的行号
    #if 1
    //set<int>::iterator it_begin = _idx_line.begin();
    set<int>::iterator begin() const{
        set<int>::iterator it_begin = _idx_line.begin();
        return it_begin; //我觉得之前的错误原因应该在局部变量
    }
    //set<int>::iterator it_end = _idx_line.end();
    set<int>::iterator end() const{
        set<int>::iterator it_end = _idx_line.end();
        return it_end;
    }
    //返回idx_line的大小-->出现的次数
    set<int>::size_type size() const{
        return _idx_line.size();
    }
    #endif
    #if 0
    set<int>::iterator begin() const {
        return _idx_line.begin();
    }

    set<int>::iterator end() const {
        return _idx_line.end();
    }

    set<int>::size_type size() const {
        return _idx_line.size();
    }
    #endif

    friend
    ostream &operator<<(ostream & os,const QueryResult& qResult);
private:
    string _world;
    set<int> _idx_line;
    //传所有的lines
    vector<string> _lines;
};
ostream &operator<<(ostream& os, const QueryResult& qResult) {
    cout << "The word: " << qResult._world << " occurs: " << qResult.size() << " times." << endl;
    for (auto it_set = qResult.begin(); it_set != qResult.end(); ++it_set) {
        int rowNumber = *it_set;
        if (rowNumber - 1 >= 0 && rowNumber - 1 < qResult._lines.size()) {
            os << "(line " << rowNumber << ")";
            os << qResult._lines[rowNumber - 1]<<endl;
        }
    }
    return os;
}

void TextQuery::readFile(const string filename){
    ifstream ifs(filename);
    if(!ifs.good()){
        cerr << "fail to open file" << endl;
        return;
    }
    int lineNumber = 0;
    string line;
    while(getline(ifs,line)){
        ++lineNumber;
        //vector存储一行的内容
        _lines.push_back(line);
        istringstream iss(line);
        string word;
        while(iss >> word){
            //处理数字问题
            bool hasDigit = false;
            for(auto & ch : word){
                if(isdigit(ch)){
                    hasDigit = true;
                    break;
                }
            }
            if(hasDigit){
                continue;
            }
            if(ispunct(word.back())){
                continue;
            }
            if(ispunct(word.front())){
                continue;
            }
            if(isupper(word[0])){
                word[0] = tolower(word[0]);
            }
            ++_dict[word];   
            _wordNumbers[word].insert(lineNumber);
        }
    }
    ifs.close();
}

QueryResult TextQuery::query(const string & word){
    auto it_word = _wordNumbers.find(word);
    QueryResult qResult(word,it_word->second,_lines);
    return qResult;
}

class AndQueryResult{
public:
    QueryResult read(const string &filename,const string &lhs,const string &rhs);
};

QueryResult AndQueryResult::read(const string &filename,const string &lhs,const string &rhs){
    TextQuery textQuery;
    textQuery.readFile(filename);
    QueryResult qleft = textQuery.query(lhs);
    QueryResult qright = textQuery.query(rhs); 
    cout<<" 138 "<<endl;
    set<int> lines;
    std::set_intersection(qleft.begin(),qleft.end(),qright.begin(),
                        qright.end(),std::inserter(lines,lines.end()));
   string temp = lhs+' '+rhs;
   for(auto &ele:lines){
    cout<<"idx :"<<ele<<" ";
   }
   cout<<endl;
   QueryResult tmp(temp,lines,textQuery.getVector());
   return tmp;
}

class Query{
public:
    Query(const string word1)
    :world(word1)
    {}
    friend
    QueryResult operator&(const Query&,const Query&);
private:
    string world;
};
QueryResult operator&(const Query& lhs,const Query& rhs){
    AndQueryResult andQureslt;
    QueryResult result = andQureslt.read("china_daily.txt",lhs.world,rhs.world);
    return result;
}


void test0(){
    Query q1("the");
    Query q2("link");
    Query q3("will");
    QueryResult result = q1 & q2;
    cout<<result<<endl;
}


//程序测试用例
int main(int argc, char *argv[])
{
    //string queryWord("the");
    //string queryWord2("link");
    //AndQueryResult andQueryResult;
    //QueryResult result = andQueryResult.read("china_daily.txt", queryWord, queryWord2);
    //cout<<result<<endl;
    test0();
    return 0;
}
